﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Diagnostics;

namespace CochinitaCorte
{
    class Cortes
    {
        public List<CutSales> CorteVentas; 
        //Constructor
        public Cortes(Parameters parameters)
        {
            CorteVentas = new List<CutSales>();
            CorteShop CS = new CorteShop();
            CorteBuilder CB;

            CB = new SalesLoader(parameters);

            CS.CreateCorte(CB);
            this.CorteVentas = CB.CorteVentas;
             
        }

        public class CorteShop
        { 
            public void CreateCorte(CorteBuilder builder)
            {
                try{
                        builder.ProcessAuditFiles();
                        builder.ValidateAuditFiles();
                        builder.LoadDetailSales();
                        builder.LoadMasterSales();
                        builder.LoadCustSales();
                }catch(Exception ex)
                {
                    throw new Exception("ERROR: " + ex.Message);
                }
            }
        }

        public abstract class CorteBuilder
        {
            public Parameters Parametros { get; set; }

            public List<CutSales> CorteVentas { get; set; }
            public List<SalesMaster> VentasCompleta { get; set; }
            public List<SalesDetail> VentasDetalle { get; set; }
            public List<FilesToProcess> Archivos { get; set; }
            public List<string> AuditFiles { get; set; }
           
            public DataLayer datalayer;

            public abstract void ProcessAuditFiles();
            public abstract void ValidateAuditFiles();
            public abstract void LoadDetailSales();
            public abstract void LoadMasterSales();
            public abstract void LoadCustSales();

        }

        public class SalesLoader : CorteBuilder
        {
            private const char Delimiter = ',';
            IFormatProvider culture = new CultureInfo("es-MX", true);

            private enum FileType
            {
                DetailFile = 'C',
                MasterFile = 'P'
            }

            private enum AuditType
            { 
               CORTE_FTP = 1,
               CORTE_LOCAL = 2
            }

            private enum ProductType
            {
                Extras=1,
                Bebidas=2,
                Alimentos=3 
            }
           
            public SalesLoader(Parameters parameters)
            {
                Parametros = parameters;
                VentasDetalle = new List<SalesDetail>();
                VentasCompleta = new List<SalesMaster>();
                CorteVentas = new List<CutSales>();
                datalayer = new DataLayer();
            }

            public override void ProcessAuditFiles()
            {
                AuditFiles = new List<string>();

                foreach (DateTime day in EachDay(Parametros.StartDate, Parametros.EndDate))
                {
                    string FileName;
                    FileName = day.Year.ToString() + (day.Month.ToString().Length > 1 ? day.Month.ToString() : "0" + day.Month.ToString()) + (day.Day.ToString().Length > 1 ? day.Day.ToString() : "0" + day.Day.ToString()) + "_";

                    foreach (int franquicia in Parametros.FranquiciasSeleccionadas)
                    {
                        AuditFiles.Add(FileName + franquicia  + "P.txt");
                        AuditFiles.Add(FileName + franquicia  + "C.txt");
                        AuditFiles.Add(FileName + franquicia  + "H.txt");
                    }

                }

            }

            public override void ValidateAuditFiles()
            {
                Archivos = new List<FilesToProcess>();

                if (Parametros.AuditType == (int)AuditType.CORTE_FTP)
                {
                    //BAJA ARCHIVOS DEL FTP AL FOLDER CARGAS 
                    //Parametros.ftpParams.downloadPath

                }
                else
                {
                    foreach (string file in AuditFiles)
                    {
                        FilesToProcess filetoprocess = new FilesToProcess();

                        filetoprocess.Franquicia = Convert.ToInt32(file.Substring(9).Replace("P", "").Replace("H", "").Replace("C", "").Replace(".txt",""));
                        filetoprocess.Date = DateTime.ParseExact(file.Substring(0, 8), "yyyyMMdd", culture); ;
                        filetoprocess.Exist = FileManager.FileExist(Parametros.settings.ftpParams.downloadPath + "/" + file);
                        filetoprocess.FileName = file;

                        Archivos.Add(filetoprocess);
                    }
                }
            }
      
            public override void LoadDetailSales()
            {
               GenericFileReader(FileType.DetailFile);
            }

            public override void LoadMasterSales()
            { 
                GenericFileReader(FileType.MasterFile);
            }

            public override void LoadCustSales()
            {
                int Count = 1;

                foreach (var archivo in Archivos.Where(n => n.FileName.IndexOf('P') != -1))// && n.Exist == true
                {
                   CorteVentas.Add(createNewCutSales(Count, archivo, VentasCompleta.Where(n => n.FileName == archivo.FileName && n.Fecha == archivo.Date && n.Cortesia != true ).ToList()));
                   Count++;
                }
            }
           
            private void GenericFileReader(FileType filetype)
            { 
                foreach (var file in Archivos.Where(n => n.FileName.IndexOf((char)filetype) != -1))
                    {
                        if (file.Exist)
                        {
                            Debug.Print(file.FileName);
                            foreach (var Row in datalayer.ReadSalesFiles(Parametros.settings.ftpParams.downloadPath + "/" + file.FileName))
                            {
                                if (Row != string.Empty)
                                {
                                    try
                                    {
                                        string[] Columns = Row.Split(Delimiter);
                                        Debug.Print("folio : " + Columns[0]);
                                        if (filetype.Equals(FileType.MasterFile))
                                            VentasCompleta.Add(createNewSaleMaster(Columns, file, this.VentasDetalle.Where(n => n.franquicia == file.Franquicia && n.Folio == Convert.ToDecimal(Columns[0]) && n.Fecha.ToShortDateString() == file.Date.ToShortDateString()).ToList()));
                                        else if (filetype.Equals(FileType.DetailFile))
                                            VentasDetalle.Add(createNewSaleDetail(Columns, file));
                                    }
                                    catch (Exception ex)
                                    {
                                        throw new Exception("Procesando archivo " + filetype.ToString() + " " + file.FileName + " " + ex.Message);
                                    }
                                }
                            }
                        }
                        else
                        {
                            string[] test = new string[17] { "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" };

                            //if (filetype.Equals(FileType.MasterFile))
                            //    VentasCompleta.Add(createNewSaleMaster(test, file, new SalesDetail()));
                            //else if (filetype.Equals(FileType.DetailFile))
                            //    VentasDetalle.Add(createNewSaleDetail(test, file));

                        }
                    }
                }
            

            private SalesDetail createNewSaleDetail(string[] detalles, FilesToProcess AuditFile)
            {

                return new SalesDetail
                                      {
                                          Folio = Convert.ToInt32(detalles[0]),
                                          Fecha = DateTime.ParseExact(detalles[5].Replace("'", ""), "dd/MM/yyyy hh:mm:ss tt", culture),
                                          NumArticulo = Convert.ToInt32(detalles[1]),
                                          IDArticulo = Convert.ToInt32(detalles[4]),
                                          CantidadArticulos = Convert.ToInt32(detalles[2]),
                                          NombreArticulo = Parametros.Productos.Where(n => n.ID == Convert.ToInt32(detalles[4])).Select(n => n.NombreArticuloCorto).FirstOrDefault(),
                                          PrecioUnitario = (Convert.ToDecimal(detalles[3]) == 0 ? 0 : Convert.ToDecimal(detalles[3]) / Convert.ToDecimal(detalles[2])),
                                          PrecioTotal = Convert.ToDecimal(detalles[3]),
                                          TipoProducto = Convert.ToInt32(detalles[9]),
                                          franquicia = AuditFile.Franquicia,
                                          Descuento = Convert.ToInt32(detalles[10]),
                                          Cajero = detalles[12].ToUpper()
                                      };
            }

            private SalesMaster createNewSaleMaster(string[] detalles, FilesToProcess AuditFile, List<SalesDetail> detalleventa)
            {
                 return new SalesMaster
                                      {
                                         Folio = Convert.ToInt32(detalles[0]),
                                         Fecha = AuditFile.Date,
                                         Efectivo = Convert.ToDecimal(detalles[10]),
                                         Dolares = Convert.ToDecimal(detalles[11]),
                                         TipoCambio = Convert.ToDecimal(detalles[12]),
                                         Tarjeta = Convert.ToDecimal(detalles[13]),
                                         Facturado = (detalles[16]=="1"),
                                         Franquicia = AuditFile.Franquicia,
                                       //  Meta = Parametros.MetasDiarias.Where(n => n.Franquicia == AuditFile.Franquicia).Select(n => (AuditFile.Date.DayOfWeek == DayOfWeek.Sunday ? n.Domingo : AuditFile.Date.DayOfWeek == DayOfWeek.Monday ? n.Lunes : AuditFile.Date.DayOfWeek == DayOfWeek.Tuesday ? n.Martes : AuditFile.Date.DayOfWeek == DayOfWeek.Wednesday ? n.Miercoles : AuditFile.Date.DayOfWeek == DayOfWeek.Thursday ? n.Jueves : AuditFile.Date.DayOfWeek == DayOfWeek.Friday ? n.Viernes : n.Sabado)).FirstOrDefault(),
                                         FileName = AuditFile.FileName,
                                         Exist = AuditFile.Exist, 
                                         SubTotal = (Parametros.DatosFiscales.Where(n => n.Franquicia == AuditFile.Franquicia).Select(n => n.PagaIVA).FirstOrDefault()) ? (detalleventa.Sum(n => n.PrecioTotal) / Parametros.settings.IVA) : Convert.ToDecimal(detalles[15]),
                                         Iva = (Parametros.DatosFiscales.Where(n => n.Franquicia == AuditFile.Franquicia).Select(n => n.PagaIVA).FirstOrDefault()) ? (Convert.ToDecimal(detalles[15]) - (detalleventa.Sum(n => n.PrecioTotal) / Parametros.settings.IVA)) : 0,
                                         Total = Convert.ToDecimal(detalles[15]),
                                         Alimentos = Convert.ToDecimal(detalleventa.Where(n => n.TipoProducto == (int)ProductType.Alimentos).Sum(n => n.PrecioTotal)),
                                         Bebidas = Convert.ToDecimal(detalleventa.Where(n => n.TipoProducto == (int)ProductType.Bebidas).Sum(n => n.PrecioTotal)),
                                         Extra = Convert.ToDecimal(detalleventa.Where(n => n.TipoProducto == (int)ProductType.Extras).Sum(n => n.PrecioTotal)),
                                         DetalleVentas = detalleventa,
                                         Cortesia = (detalles[4] == "1")
                                    };

            }

            private CutSales createNewCutSales(int index, FilesToProcess archivo, List<SalesMaster> detallemaster)
            {
                return new CutSales 
                { 
                    NumCorte = index,
                    Fecha = archivo.Date,
                    Meta = Parametros.MetasDiarias.Where(n => n.Franquicia == archivo.Franquicia).Select(n => (archivo.Date.DayOfWeek == DayOfWeek.Sunday ? n.Domingo : archivo.Date.DayOfWeek == DayOfWeek.Monday ? n.Lunes : archivo.Date.DayOfWeek == DayOfWeek.Tuesday ? n.Martes : archivo.Date.DayOfWeek == DayOfWeek.Wednesday ? n.Miercoles : archivo.Date.DayOfWeek == DayOfWeek.Thursday ? n.Jueves : archivo.Date.DayOfWeek == DayOfWeek.Friday ? n.Viernes : n.Sabado)).FirstOrDefault(),
                    Franquicia = archivo.Franquicia,
                    Alimentos = detallemaster.Sum(n => n.Alimentos),
                    Bebidas = detallemaster.Sum(n => n.Bebidas),
                    Extra = detallemaster.Sum(n => n.Extra),
                    SubTotal = detallemaster.Sum(n => n.SubTotal),
                    Iva = detallemaster.Sum(n => n.Iva),
                    Total = detallemaster.Sum(n => n.Total),
                    tickets = detallemaster
                };
            }
           
            private IEnumerable<DateTime> EachDay(DateTime from, DateTime thru)
            {
                for (var day = from.Date; day.Date <= thru.Date; day = day.AddDays(1))
                    yield return day;
            }
          
        }
    }
}
